import java.math.BigDecimal;

public class DataTypeAndVariable {
    public static void func(String[] args) {
        System.out.print("打印不换行");
        System.out.println("打印换行");
        System.out.printf("%d\n", 10);
        System.out.printf("%s, %c", "String", 'c');
    }

    /**
     * 1、 int 几个字节？   4个字节  不管你是多少为的操作系统   4个字节
     * 16  32   64
     * 充分说明一个问题：可移植性强
     * <p>
     * 2、Java当中的int  没有所谓的无符号类型   统一都是有符号的
     * <p>
     * 3、取值范围是多少？ -2^31  -  2^31 -1
     * <p>
     * 4、变量的命名：小驼峰  -》 数字  字母 下划线 美元符号 组成的
     * 不能以数字开头
     * <p>
     * 5、变量定义不初始化 可不可以？  不可以，Java比较安全，如果不初始化就使用，编译器就会报错 不是警告！！！
     * <p>
     * 数据类型          关键字         内存占用        范围
     * 字节型           byte            1 字节        -128 ~ 127
     * 短整型           short           2 字节        -32768 ~ 32767
     * 整型             int             4 字节        -2^31 ~ 2^31-1
     * 长整型           long            8 字节        -2^63 ~ 2^63-1
     * 单精度浮点数      float          4 字节        有范围，一般不关注
     * 双精度浮点数      double         8 字节        有范围，一般不关注
     * 字符型           char           2 字节         0 ~ 65535
     * 布尔型           boolean     没有明确规定      true 和 false
     * <p>
     * 注意：
     * 不论是在16位系统还是32位系统，int都占用4个字节，long都占8个字节
     * 整形和浮点型都是带有符号的
     * 整型默认为int型，浮点型默认为double
     * 字符串属于引用类型
     *
     * @param args [description]
     */
    public static void main2(String[] args) {
        //注意事项：
        //1. int不论在何种系统下都是4个字节
        //2. 推荐使用方式一定义，如果没有合适的初始值，可以设置为0
        //3. 在给变量设置初始值时，值不能超过int的表示范围，否则会导致溢出
        //4. 变量在使用之前必须要赋初值，否则编译报错
        //5. int的包装类型为 Integer
        int a3 = 10;
        System.out.println(a3);
        //溢出
        System.out.println(Integer.MAX_VALUE + 1);
        //溢出
        System.out.println(Integer.MIN_VALUE - 1);
        int maxNum = 10;
        int max_num = 10;
        int max3_num = 10;
        int max$num = 10;

        int _________ = 101;
        int ____________ = 10;
        int _____________________ = 10;
        System.out.println(_________);//典型的坑人手法

        int 钱 = 100;//Unicode字符集 -》 拉丁文  中文
        System.out.println(钱);

        int b = 0;
        System.out.println(b);
    }

    public static void main3(String[] args) {
        long a = 10;
        System.out.println(a);
        long c = 10L; // 为了区分int和long类型，一般建议：long类型变量的初始值之后加L或者l
        long d = 10l; // 一般更加以加大写L，因为小写l与1不好区分
        //这个是包装类Long而不是基本的数据类型long
        //// long型变量所能表示的范围：这个数据范围远超过 int 的表示范围. 足够绝大部分的工程场景使用
        System.out.println(Long.MAX_VALUE);
        System.out.println(Long.MIN_VALUE);
    }

    public static void main4(String[] args) {
//      java 中的浮点数（float 和 double）使用 IEEE 754 标准进行表示，这是一种二进制浮点数表示方法
//      由于浮点数在二进制表示中的精度限制，某些十进制小数无法精确表示，这会导致在计算过程中出现微小的误差
        double a = 1.1;
        System.out.println(a * a);

        //如果你需要高精度的浮点数运算，可以使用 BigDecimal 类
        //BigDecimal 类提供了对浮点数进行高精度运算的方法
        //字符串初始化 BigDecimal：精确地解析和表示十进制数，避免了浮点数的二进制近似误差
        BigDecimal bigDecimal = new BigDecimal("1.1");
        System.out.println(bigDecimal.multiply(bigDecimal));

        //浮点数初始化 BigDecimal: 使用浮点数的二进制近似值，导致 BigDecimal 内部的值不精确
        BigDecimal bigDecimal2 = new BigDecimal(1.1);
        System.out.println(bigDecimal2.multiply(bigDecimal2));
    }

    public static void main5(String[] args) {
        //在Java中，浮点数默认是以double类型表示的
        // 因此，如果你想明确地表示一个float类型的浮点数，必须在数值后面加上f或F
        // 同样地，如果你想明确地表示一个double类型的浮点数，可以在数值后面加上d或D
        // 虽然这是可选的，因为不加d默认也是double类型
        float f1 = 12.5f;
        //12.5 是 double 类型的字面值，试图将 double 类型的字面值赋值给 float 类型变量时
        //会导致类型不兼容的错误，因为 double 精度更高，需要进行类型转换才能赋值给float
//        float f2 = 12.5;
        double d1 = 12.5d;
        double d2 = 12.5;
        //只是有一些浮点数相乘是有误差的,有一些浮点数相乘就没有误差,就像下面的这个
        System.out.println(f1 * f1);
        System.out.println(d1 * d1);
        System.out.println(d2 * d2);
    }

    public static void main6(String[] args) {
        char ch = '特';//2个字节
        char ch2 = 97;
        System.out.println(ch);
        //打印的是a,对应的ASCII值为97
        System.out.println(ch2);
    }

    public static void main7(String[] args) {
        byte b = 10;//1个字节
        System.out.println(b);

        byte b2 = -128;
        byte b3 = 127;
        System.out.println(b2);
        System.out.println(b3);
        byte b4 = (byte) 170;
        System.out.println(b4);

        int i = 2147483647;
        System.out.println(i);
    }

    public static void main8(String[] args) {

        boolean flg = true;
        System.out.println(flg);
        boolean flg2 = false;
        System.out.println(flg2);

//        注意事项：
//        1. boolean 类型的变量只有两种取值, true 表示真, false 表示假.
//        2. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法
    }

    //自动类型转换(隐式)
    // 即：代码不需要经过任何处理，在代码编译时，编译器会自动进行处理
    // 特点：数据范围小的转为数据范围大的时会自动进行
    public static void main9() {
        System.out.println(1024); // 整型默认情况下是int
        System.out.println(3.14); // 浮点型默认情况下是double

        int a = 100;
        long b = 10L;
        b = a; // a和b都是整形，a的范围小，b的范围大，当将a赋值给b时，编译器会自动将a提升为long类型，然后赋值
//        a = b; // 编译报错，long的范围比int范围大，会有数据丢失，不安全

        float f = 3.14F;
        double d = 5.12;
        d = f; // 编译器会将f转换为double，然后进行赋值
//        f = d; // double表示数据范围大，直接将float交给double会有数据丢失，不安全
        byte b1 = 100; // 编译通过，100没有超过byte的范围，编译器隐式将100转换为byte
//        byte b2 = 257; // 编译失败，257超过了byte的数据范围，有数据丢失
    }

    //强制类型转换(显式)：
    // 当进行操作时，代码需要经过一定的格式处理，不能自动完成。特点：数据范围大的到数据范围小的
    public static void main10() {
        int a = 10;
        long b = 100L;
        b = a; // int-->long，数据范围由小到大，隐式转换
        a = (int) b; // long-->int, 数据范围由大到小，需要强转，否则编译失败

        float f = 3.14F;
        double d = 5.12;
        d = f; // float-->double，数据范围由小到大，隐式转换
        f = (float) d; // double-->float, 数据范围由大到小，需要强转，否则编译失败

//        a = d; // 报错，类型不兼容
        a = (int) d; // int没有double表示的数据范围大，需要强转，小数点之后全部丢弃

        byte b1 = 100; // 100默认为int，没有超过byte范围，隐式转换
        byte b2 = (byte) 257; // 257默认为int，超过byte范围，需要显示转换，否则报错

        boolean flag = true;
//        a = flag; // 编译失败：类型不兼容,并且boolean无法转换为int,强制转换失败
//        flag = (boolean) a; // 编译失败：类型不兼容,并且int无法转换为boolean,强制转换失败

        //注意事项：
        //1. 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型
        //2. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失
        //3. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查
        //4. 强制类型转换不一定能成功，不相干的类型不能互相转换
    }

    //类型提升
    //不同类型的数据之间相互运算时，数据类型小的会被提升到数据类型大的
    //1. int与long之间：int会被提升为long
    public static void main11() {
        int a = 10;
        long b = 20;
//        int c = a + b; // 编译出错: a + b==》int + long--> long + long 赋值给int时会丢失数据
        long d = a + b; // 编译成功：a + b==>int + long--->long + long 赋值给long
    }

    //byte与byte的运算
    public static void main12() {
        byte a = 10;
        byte b = 20;
        //byte 和 byte 都是相同类型, 但是出现编译报错. 原因是, 虽然 a 和 b 都是 byte
        // 但是计算 a + b 会先将 a和 b 都提升成 int, 再进行计算, 得到的结果也是 int, 这是赋给 c, 就会出现上述错误
        //由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据
        // 为了硬件上实现方便, 诸如 byte 和 short
        //这种低于 4 个字节的类型, 会先提升成 int, 再参与计算
//        byte c = (byte)a + b;
        byte c = (byte) (a + b);
        System.out.println(c);

//        【类型提升小结:】
//        1. 不同类型的数据混合运算, 范围小的会提升成范围大的
//        2. 对于 short, byte 这种比 4 个字节小的类型, 会先提升成 4 个字节的 int , 再运算
    }

    //    字符串类型
//    在Java中使用String类定义字符串类型，比如：
    public static void main13() {
        String s1 = "hello";
        String s2 = " world";
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1 + s2); // s1+s2表示：将s1和s2进行拼接

        //将int转化成String
        int num = 10;
        //方法1
        String str1 = num + "";
        //方法2
        String str2 = String.valueOf(num);

        //将String转换成int
        String str = "100";
        //parseInt 是 Integer 类中的一个静态方法，它用于将字符串类型的数字转换为 int 类型
        int num1 = Integer.parseInt(str);
    }

    public static void main(String[] args) {
//        func(args);
//        main2(args);
//        main3(args);
//        main4(args);
//        main5(args);
//        main6(args);
//        main7(args);
//        main8(args);
//        main9();
//        main10();
//        main11();
//        main12();
        main13();
    }
}
